
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using GruntXProductions;
using Viper;
using Viper.Opcodes;

namespace Diamond
{
	public partial class CodeGen 
	{
		private Stack<string> breakLabels = new Stack<string>();
		public VType GuessType(SyntaxNode sn)
		{
			if(sn is IntLiteral)
					return VType.Dword;
			else if (sn is StringLiteral)
				return VType.String;
			else if (sn is FunctionCall)
			{
				return getVType(GetReturnType(sn as FunctionCall));
			}
			else if (sn is Operator)
			{
				return GuessType(((Operator)sn).Op1);
			}
			else if (sn is SymbolRef)
				return Symbols.GetType(((SymbolRef)sn).Value);
			return VType.Dword;
			
		}
        public VType getVType(string stR)
        {
                if(stR == "byte")
                        return VType.Byte;
                else if (stR == "string")
                        return VType.String;
                else if (stR == "int")
                        return VType.Dword;
                else if (stR == "real")
                        return VType.Float;
                else
                        return VType.Dword;
        }
		public VType GuessType(Expression exp)
		{
			foreach(SyntaxNode sn in exp.Items)
			{
				return GuessType(sn);
			}
			return VType.Object;
		}
		public string GetTypeName(VType v)
		{
			if(v == VType.Dword)
				return "int";
			else if (v == VType.String)
				return "string";
			return "object";
		}
		public string GetMethodName(Method meth)
		{
			
			meth.Arguments.Reverse();
			string name = meth.Name ;
			foreach(Declaration decl in meth.Arguments)
				name += "_" +decl.Type ;
			meth.Arguments.Reverse();
			return name;
		}
		public string GetMethodName(OperatorOverload meth)
		{
			string name = meth.theOperator ;
			foreach(Declaration decl in meth.Arguments)
				name += "_" + decl.Type;
			return name;
		}
		public string GetMethodName(FunctionCall func)
		{
			string name = func.Target ;
			func.Arguments.Reverse();
			foreach(Expression exp in func.Arguments)
			{
				name += "_" + GetTypeName(GuessType(exp));
			}
			func.Arguments.Reverse();
			return name;
		}
		public Method getMethod(FunctionCall func)
		{
			foreach(SyntaxNode sn in AST)
			{
				if(sn is Method)
				{
					if(GetMethodName(func) == GetMethodName(sn as Method))
						return sn as Method;
				}
				else if(sn is DiamondClass)
				{
					if(getMethod (func, ((DiamondClass)sn).Functions) != null)
						return getMethod (func, ((DiamondClass)sn).Functions);
				}
			}
			return null;
		}
		public Method getMethod(FunctionCall func, List<Method> methods)
		{
			foreach(Method sn in methods)
			{
				if(GetMethodName(func) == GetMethodName(sn as Method))
					return sn as Method;
				
				
			}
			return null;
		}
		public string GetReturnType(FunctionCall func)
		{
			foreach(SyntaxNode sn in AST)
			{
				if(sn is Method)
				{
					Method m = sn as Method;
					if(m.Name == func.Target)
						return m.Type;
				}
			}
			return "";
		}
	}
	
}
